From 2ec558319c08c178032bb1fe5ae7d10ff680c56f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 11:00:28 +0100 Subject: [PATCH] Clean up xenoprof code a bit. The main remaining TODO is to clean up the xenoprof hypercall interface. Signed-off-by: Keir Fraser --- .../arch/i386/oprofile/Makefile | 2 +- .../arch/x86_64/oprofile/Makefile | 2 +- xen/arch/x86/domain.c | 2 - xen/arch/x86/oprofile/nmi_int.c | 22 +- xen/arch/x86/oprofile/xenoprof.c | 225 ++++++++---------- xen/common/event_channel.c | 1 + xen/include/public/xen.h | 4 +- xen/include/public/xenoprof.h | 11 + xen/include/xen/sched.h | 4 +- xen/include/xen/xenoprof.h | 16 +- 10 files changed, 134 insertions(+), 155 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile index d283cd6c4d..e596c39c09 100644 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile @@ -6,7 +6,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -ifdef CONFIG_X86_XEN +ifdef CONFIG_XEN oprofile-y := $(DRIVER_OBJS) xenoprof.o else oprofile-y := $(DRIVER_OBJS) init.o backtrace.o diff --git a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile index 2f9d03b30d..589a7966e8 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile +++ b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile @@ -11,7 +11,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -ifdef +ifdef CONFIG_XEN OPROFILE-y := xenoprof.o else OPROFILE-y := init.o backtrace.o diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 8c0bb136fa..a657fba2eb 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -915,8 +915,6 @@ static void relinquish_memory(struct domain *d, struct list_head *list) spin_unlock_recursive(&d->page_alloc_lock); } -extern void free_xenoprof_pages(struct domain *d); - void domain_relinquish_resources(struct domain *d) { struct vcpu *v; diff --git a/xen/arch/x86/oprofile/nmi_int.c b/xen/arch/x86/oprofile/nmi_int.c index d9495b0566..3978428a32 100644 --- a/xen/arch/x86/oprofile/nmi_int.c +++ b/xen/arch/x86/oprofile/nmi_int.c @@ -45,31 +45,23 @@ extern size_t strlcpy(char *dest, const char *src, size_t size); int nmi_callback(struct cpu_user_regs *regs, int cpu) { - int xen_mode = 0; - int ovf; + int xen_mode, ovf; ovf = model->check_ctrs(cpu, &cpu_msrs[cpu], regs); xen_mode = ring_0(regs); - if ( ovf ) - { - if ( is_active(current->domain) ) - { - if ( !xen_mode ) - { - send_guest_vcpu_virq(current, VIRQ_XENOPROF); - } - } - } + if ( ovf && is_active(current->domain) && !xen_mode ) + send_guest_vcpu_virq(current, VIRQ_XENOPROF); + return 1; } -static void nmi_cpu_save_registers(struct op_msrs * msrs) +static void nmi_cpu_save_registers(struct op_msrs *msrs) { unsigned int const nr_ctrs = model->num_counters; unsigned int const nr_ctrls = model->num_controls; - struct op_msr * counters = msrs->counters; - struct op_msr * controls = msrs->controls; + struct op_msr *counters = msrs->counters; + struct op_msr *controls = msrs->controls; unsigned int i; for (i = 0; i < nr_ctrs; ++i) { diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c index 529c67b601..ecd9abd2cf 100644 --- a/xen/arch/x86/oprofile/xenoprof.c +++ b/xen/arch/x86/oprofile/xenoprof.c @@ -14,18 +14,18 @@ int active_domains[MAX_OPROF_DOMAINS]; int active_ready[MAX_OPROF_DOMAINS]; -unsigned int adomains = 0; -unsigned int activated = 0; -struct domain *primary_profiler = NULL; +unsigned int adomains; +unsigned int activated; +struct domain *primary_profiler; int xenoprof_state = XENOPROF_IDLE; -u64 total_samples = 0; -u64 invalid_buffer_samples = 0; -u64 corrupted_buffer_samples = 0; -u64 lost_samples = 0; -u64 active_samples = 0; -u64 idle_samples = 0; -u64 others_samples = 0; +u64 total_samples; +u64 invalid_buffer_samples; +u64 corrupted_buffer_samples; +u64 lost_samples; +u64 active_samples; +u64 idle_samples; +u64 others_samples; extern int nmi_init(int *num_events, int *is_primary, char *cpu_type); @@ -39,16 +39,8 @@ extern void nmi_release_counters(void); int is_active(struct domain *d) { - xenoprof_t *x = d->xenoprof; - if ( x ) - { - if ( x->domain_type == XENOPROF_DOMAIN_ACTIVE ) - return 1; - else - return 0; - } - else - return 0; + struct xenoprof *x = d->xenoprof; + return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_ACTIVE)); } int is_profiled(struct domain *d) @@ -65,25 +57,24 @@ static void xenoprof_reset_stat(void) active_samples = 0; idle_samples = 0; others_samples = 0; - - return; } static void xenoprof_reset_buf(struct domain *d) { int j; - xenoprof_buf_t *buf; + struct xenoprof_buf *buf; - if ( !d->xenoprof ) + if ( d->xenoprof == NULL ) { - printk("xenoprof_reset_buf: ERROR - Unexpected Xenoprof NULL pointer \n"); + printk("xenoprof_reset_buf: ERROR - Unexpected " + "Xenoprof NULL pointer \n"); return; } - for ( j=0; jxenoprof->vcpu[j].buffer; - if ( buf ) + if ( buf != NULL ) { buf->event_head = 0; buf->event_tail = 0; @@ -93,62 +84,57 @@ static void xenoprof_reset_buf(struct domain *d) int active_index(struct domain *d) { - int i; - int id; + int i, id = d->domain_id; - id = d->domain_id; - for ( i=0; ixenoprof; - if ( x ) - { - x->domain_ready = 1; - x->domain_type = XENOPROF_DOMAIN_ACTIVE; - active_ready[ind] = 1; - activated++; - return 0; - } - else + if ( x == NULL ) return -EPERM; + + x->domain_ready = 1; + x->domain_type = XENOPROF_DOMAIN_ACTIVE; + active_ready[ind] = 1; + activated++; + + return 0; } int reset_active(struct domain *d) { int ind; - xenoprof_t *x; + struct xenoprof *x; ind = active_index(d); - if ( ind <0 ) + if ( ind < 0 ) return -EPERM; x = d->xenoprof; - if ( x ) - { - x->domain_ready = 0; - x->domain_type = XENOPROF_DOMAIN_IGNORED; - active_ready[ind] = 0; - activated--; - if ( activated <= 0 ) - adomains = 0; - return 0; - } - else + if ( x == NULL ) return -EPERM; + + x->domain_ready = 0; + x->domain_type = XENOPROF_DOMAIN_IGNORED; + active_ready[ind] = 0; + activated--; + if ( activated <= 0 ) + adomains = 0; + + return 0; } int set_active_domains(int num) @@ -157,13 +143,13 @@ int set_active_domains(int num) int i; struct domain *d; - /* reset any existing active domains from previous runs */ - for ( i=0; i= MAX_OPROF_DOMAINS ) return -E2BIG; - else - { - active_domains[num] = primary_profiler->domain_id; - num++; - } + active_domains[num] = primary_profiler->domain_id; + num++; } adomains = num; activated = 0; - for ( i=0; idomain) ) { - others_samples++; - return; + others_samples++; + return; } v = &vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id]; /* Sanity check. Should never happen */ - if ( !v->buffer ) + if ( v->buffer == NULL ) { invalid_buffer_samples++; return; @@ -269,20 +251,19 @@ char *alloc_xenoprof_buf(struct domain *d, int npages) int i, order; /* allocate pages to store sample buffer shared with domain */ - order = get_order_from_pages(npages); - rawbuf = alloc_xenheap_pages(order); - if( rawbuf == NULL ) + order = get_order_from_pages(npages); + rawbuf = alloc_xenheap_pages(order); + if ( rawbuf == NULL ) { printk("alloc_xenoprof_buf(): memory allocation failed\n"); return 0; } /* Share pages so that kernel can map it */ - for ( i=0; ixenoprof = xmalloc(xenoprof_t); + d->xenoprof = xmalloc(struct xenoprof); - if ( !d->xenoprof ) + if ( d->xenoprof == NULL ) { printk ("alloc_xenoprof_struct(): memory " "allocation (xmalloc) failed\n"); @@ -305,23 +286,23 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples) memset(d->xenoprof, 0, sizeof(*d->xenoprof)); nvcpu = 0; - for_each_vcpu(d, v) + for_each_vcpu ( d, v ) nvcpu++; /* reduce buffer size if necessary to limit pages allocated */ - bufsize = sizeof(xenoprof_buf_t) + + bufsize = sizeof(struct xenoprof_buf) + (max_samples - 1) * sizeof(struct event_log); max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; if ( bufsize > max_bufsize ) { bufsize = max_bufsize; - max_samples = ( (max_bufsize - sizeof(xenoprof_buf_t)) / + max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) / sizeof(struct event_log) ) + 1; } npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; d->xenoprof->rawbuf = alloc_xenoprof_buf(d, npages); - if ( !d->xenoprof->rawbuf ) + if ( d->xenoprof->rawbuf == NULL ) { xfree(d->xenoprof); d->xenoprof = NULL; @@ -335,12 +316,12 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples) d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; /* Update buffer pointers for active vcpus */ - i=0; - for_each_vcpu(d, v) + i = 0; + for_each_vcpu ( d, v ) { d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples; d->xenoprof->vcpu[v->vcpu_id].buffer = - (xenoprof_buf_t *)&d->xenoprof->rawbuf[i * bufsize]; + (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize]; d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples; d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id; @@ -355,21 +336,21 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples) void free_xenoprof_pages(struct domain *d) { - xenoprof_t *x; + struct xenoprof *x; int order; x = d->xenoprof; + if ( x == NULL ) + return; - if ( x ) + if ( x->rawbuf != NULL ) { - if ( x->rawbuf ) - { - order = get_order_from_pages(x->npages); - free_xenheap_pages(x->rawbuf, order); - } - xfree(x); - d->xenoprof = NULL; + order = get_order_from_pages(x->npages); + free_xenheap_pages(x->rawbuf, order); } + + xfree(x); + d->xenoprof = NULL; } int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) @@ -386,13 +367,13 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) if ( ret < 0 ) goto err; - /* we allocate xenoprof struct and buffers only at first time - xenoprof_init is called. Memory is then kept until domain is destroyed */ - if ( !d->xenoprof ) - { - if ( (ret = alloc_xenoprof_struct(d, max_samples)) < 0 ) - goto err; - } + /* + * We allocate xenoprof struct and buffers only at first time xenoprof_init + * is called. Memory is then kept until domain is destroyed. + */ + if ( (d->xenoprof == NULL) && + ((ret = alloc_xenoprof_struct(d, max_samples)) < 0) ) + goto err; xenoprof_reset_buf(d); @@ -420,11 +401,11 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) return ret; } -#define PRIV_OP(op) ( (op == XENOPROF_set_active) \ +#define PRIV_OP(op) ( (op == XENOPROF_set_active) \ || (op == XENOPROF_reserve_counters) \ - || (op == XENOPROF_setup_events) \ - || (op == XENOPROF_start) \ - || (op == XENOPROF_stop) \ + || (op == XENOPROF_setup_events) \ + || (op == XENOPROF_start) \ + || (op == XENOPROF_stop) \ || (op == XENOPROF_release_counters) \ || (op == XENOPROF_shutdown)) @@ -432,7 +413,7 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) { int ret = 0; - if ( PRIV_OP(op) && current->domain != primary_profiler ) + if ( PRIV_OP(op) && (current->domain != primary_profiler) ) { printk("xenoprof: dom %d denied privileged operation %d\n", current->domain->domain_id, op); @@ -468,9 +449,7 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) return -EPERM; if ( adomains == 0 ) - { set_active_domains(0); - } if ( copy_from_user((void *)&counter_config, (void *)arg1, arg2 * sizeof(struct op_counter_config)) ) @@ -491,15 +470,12 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) break; case XENOPROF_start: + ret = -EPERM; if ( (xenoprof_state == XENOPROF_READY) && (activated == adomains) ) - { ret = nmi_start(); - } - else - ret= -EPERM; - if ( !ret ) + if ( ret == 0 ) xenoprof_state = XENOPROF_PROFILING; break; @@ -518,18 +494,19 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) break; case XENOPROF_release_counters: + ret = -EPERM; if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || (xenoprof_state == XENOPROF_READY) ) { xenoprof_state = XENOPROF_IDLE; nmi_release_counters(); nmi_disable_virq(); + ret = 0; } - else - ret = -EPERM; break; case XENOPROF_shutdown: + ret = -EPERM; if ( xenoprof_state == XENOPROF_IDLE ) { activated = 0; @@ -537,8 +514,6 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) primary_profiler = NULL; ret = 0; } - else - ret = -EPERM; break; default: diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index ccb96b0f65..a217e1be8b 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -57,6 +57,7 @@ static int virq_is_global(int virq) { case VIRQ_TIMER: case VIRQ_DEBUG: + case VIRQ_XENOPROF: rc = 0; break; default: diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index c79bc6f859..e18fbf9669 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -78,8 +78,8 @@ #define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */ #define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */ #define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */ -#define VIRQ_XENOPROF 7 /* XenOprofile interrupt: new sample available */ -#define NR_VIRQS 9 +#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */ +#define NR_VIRQS 8 /* * MMU-UPDATE REQUESTS diff --git a/xen/include/public/xenoprof.h b/xen/include/public/xenoprof.h index b8ea8a8aba..134df887c4 100644 --- a/xen/include/public/xenoprof.h +++ b/xen/include/public/xenoprof.h @@ -48,6 +48,7 @@ typedef struct xenoprof_buf { uint64_t lost_samples; struct event_log event_log[1]; } xenoprof_buf_t; +DEFINE_GUEST_HANDLE(xenoprof_buf_t); typedef struct xenoprof_init_result { int32_t num_events; @@ -57,7 +58,17 @@ typedef struct xenoprof_init_result { uint64_t buf_maddr; char cpu_type[XENOPROF_CPU_TYPE_SIZE]; } xenoprof_init_result_t; +DEFINE_GUEST_HANDLE(xenoprof_init_result_t); +typedef struct xenoprof_counter_config { + unsigned long count; + unsigned long enabled; + unsigned long event; + unsigned long kernel; + unsigned long user; + unsigned long unit_mask; +} xenoprof_counter_config_t; +DEFINE_GUEST_HANDLE(xenoprof_counter_config_t); #endif /* __XEN_PUBLIC_XENOPROF_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 791c5665b9..1ea48aae7d 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -157,8 +157,8 @@ struct domain /* Control-plane tools handle for this domain. */ xen_domain_handle_t handle; - /* pointer to xenoprof data (oprofile support) */ - xenoprof_t *xenoprof; + /* OProfile support. */ + struct xenoprof *xenoprof; }; struct domain_setup_info diff --git a/xen/include/xen/xenoprof.h b/xen/include/xen/xenoprof.h index f763eb1077..5ecb755f42 100644 --- a/xen/include/xen/xenoprof.h +++ b/xen/include/xen/xenoprof.h @@ -20,13 +20,12 @@ #define XENOPROF_READY 2 #define XENOPROF_PROFILING 3 - -typedef struct xenoprof_vcpu { +struct xenoprof_vcpu { int event_size; - xenoprof_buf_t *buffer; -} xenoprof_vcpu_t; + struct xenoprof_buf *buffer; +}; -typedef struct xenoprof { +struct xenoprof { char* rawbuf; int npages; int nbuf; @@ -34,7 +33,10 @@ typedef struct xenoprof { int domain_type; int domain_ready; int is_primary; - xenoprof_vcpu_t vcpu [MAX_VIRT_CPUS]; -} xenoprof_t; + struct xenoprof_vcpu vcpu [MAX_VIRT_CPUS]; +}; + +struct domain; +void free_xenoprof_pages(struct domain *d); #endif /* __XEN__XENOPROF_H__ */ -- 2.30.2